package com.baomidou.springmvc.service.system.impl;

import java.util.Date;
import java.util.List;
import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.baomidou.springmvc.exception.myexception.ServiceException;
import com.baomidou.springmvc.mapper.system.PrizeMapper;
import com.baomidou.springmvc.model.enums.PrizeTypeEnum;
import com.baomidou.springmvc.model.system.DrawPrizeRecord;
import com.baomidou.springmvc.model.system.Prize;
import com.baomidou.springmvc.service.system.IDrawPrizeRecordService;
import com.baomidou.springmvc.service.system.IPrizeService;

@Service
public class PrizeServiceImpl extends ServiceImpl<PrizeMapper, Prize> implements IPrizeService{

	private static Logger LOGGER = LoggerFactory.getLogger(PrizeServiceImpl.class);
	
	@Autowired
	private IDrawPrizeRecordService drawPrizeRecordService;
	
	@SuppressWarnings({ "serial", "rawtypes", "unchecked" })
	@Override
	public List<Prize> findList() {
		EntityWrapper< Prize> ew = new EntityWrapper<Prize>();
		ew.orderBy("type", true);
		List<Prize> prizeList = selectList(ew);
		return prizeList;
	}

	@Override
	public Prize find(Prize p) {
		return baseMapper.find(p.getType());
	}

	/**
	 * 抽奖核心算法
	 */
	@Override
	public int getPrizeIndex(List<Prize> prizeList) {
		int weightSum = 0;
		int randN = -1;
		for(Prize prz : prizeList) {
			weightSum += prz.getWeight();
		}
		int rand = new Random().nextInt(weightSum)+1;
		int d1 = 0;
		int d2 = 0;
		
		for(int i = 0; i < prizeList.size(); i++) {
			d2 += prizeList.get(i).getWeight();
			if(i==0) {
				d1 =0;
			}else {
				d1 +=  prizeList.get(i-1).getWeight();
			}
			if(rand >= d1&& rand <=d2) {
				randN = i;
				break;
			}
		}
		return randN;
	}

	/**
	 * 自定义规则
	 */
	@	Transactional(readOnly = false)
	@Override
	public int getFinallyPrizeIndex(List<Prize> prizeList,int randN,long nowtime,long day14s,long day14e,
			long day15s,long day15e,long day16s,long day16e,long day17s,long day17e,long day18s,long day18e,
			String openId) {
				
				//最终的奖品代号
				int finallyPrizeIndex = -1;
		
				//如果抽到特等奖
				if(PrizeTypeEnum.UTR.getVal()==randN) {
					LOGGER.error("**********怎么可能抽到特等奖，肯定出BUG了**********");
					throw new ServiceException("抽奖程序异常");
				}
				
				//如果抽到一等奖
				else if(PrizeTypeEnum.SSR.getVal()==randN) {
					//1.判断当前日期是否为day17
					if((day17s<=nowtime&&nowtime<=day17e)) {
						//2.查询一等奖数量
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.SSR.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day17 = pp.getDay17();
						if(0==day17) {
							//表示奖品已经被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day17 = pp.getDay17()-1;
							pp.setDay17(day17);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.SSR.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.SSR.getVal();
						}
					}else {
						//不是在day17，重新抽奖
						int randNN = this.getPrizeIndex(prizeList);
						//递归执行这个判断逻辑
						finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
					}
				}
				
				//如果抽到二等奖
				else if(PrizeTypeEnum.SR.getVal()==randN) {
					//判断今天是day几
					//如果是11.14==>数量是2
					if((day14s<=nowtime&&nowtime<=day14e)) {
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.SR.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day14 = pp.getDay14();
						if(0==day14) {
							//表示奖品已被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day14 = pp.getDay14()-1;
							pp.setDay14(day14);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.SR.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.SR.getVal();
						}
					}
					//如果今天是11.15==>数量是5
					else if((day15s<=nowtime&&nowtime<=day15e)) {
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.SR.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day15 = pp.getDay15();
						if(0==day15) {
							//表示奖品已被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day15 = pp.getDay15()-1;
							pp.setDay15(day15);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.SR.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.SR.getVal();
						}
					}
					//如果今天是11.16==>数量是5
					else if((day16s<=nowtime&&nowtime<=day16e)) {
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.SR.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day16 = pp.getDay16();
						if(0==day16) {
							//表示奖品已被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day16 = pp.getDay16()-1;
							pp.setDay16(day16);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.SR.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.SR.getVal();
						}
					}
					//如果今天是11.17==>数量是5
					else if((day17s<=nowtime&&nowtime<=day17e)) {
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.SR.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day17 = pp.getDay17();
						if(0==day17) {
							//表示奖品已被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day17 = pp.getDay17()-1;
							pp.setDay17(day17);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.SR.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.SR.getVal();
						}
					}
					//如果今天是11.18==>数量是3
					else if((day18s<=nowtime&&nowtime<=day18e)) {
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.SR.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day18 = pp.getDay18();
						if(0==day18) {
							//表示奖品已被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day18 = pp.getDay18()-1;
							pp.setDay18(day18);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.SR.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.SR.getVal();
						}
					}else {
						//错误
						throw new  ServiceException("抽奖日期有误");
					}
				}
				
				//如果抽到三等奖
				else if(PrizeTypeEnum.R.getVal() ==randN) {
					//判断今天是day几
					//如果是11.14==>数量是5
					if((day14s<=nowtime&&nowtime<=day14e)) {
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.R.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day14 = pp.getDay14();
						if(0==day14) {
							//表示奖品已被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day14 = pp.getDay14()-1;
							pp.setDay14(day14);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.R.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.R.getVal();
						}
					}
					//如果今天是11.15==>数量是10
					else if((day15s<=nowtime&&nowtime<=day15e)) {
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.R.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day15 = pp.getDay15();
						if(0==day15) {
							//表示奖品已被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day15 = pp.getDay15()-1;
							pp.setDay15(day15);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.R.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.R.getVal();
						}
					}
					//如果今天是11.16==>数量是10
					else if((day16s<=nowtime&&nowtime<=day16e)) {
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.R.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day16 = pp.getDay16();
						if(0==day16) {
							//表示奖品已被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day16 = pp.getDay16()-1;
							pp.setDay16(day16);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.R.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.R.getVal();
						}
					}
					//如果今天是11.17==>数量是10
					else if((day17s<=nowtime&&nowtime<=day17e)) {
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.R.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day17 = pp.getDay17();
						if(0==day17) {
							//表示奖品已被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day17 = pp.getDay17()-1;
							pp.setDay17(day17);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.R.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.R.getVal();
						}
					}
					//如果今天是11.18==>数量是5
					else if((day18s<=nowtime&&nowtime<=day18e)) {
						Prize pp = new Prize();
						pp.setType(PrizeTypeEnum.R.getVal());
						pp = this.find(pp);
						if(null==pp) {
							throw new ServiceException("奖品信息有误");
						}
						int day18 = pp.getDay18();
						if(0==day18) {
							//表示奖品已被抽走，重新抽奖
							int randNN = this.getPrizeIndex(prizeList);
							//递归执行这个判断逻辑
							finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
						}else {
							day18 = pp.getDay18()-1;
							pp.setDay18(day18);
							if(!this.updateById(pp)){
								throw new ServiceException("更新奖品数量失败");
							}
							//生成中奖记录
							DrawPrizeRecord dprd = new DrawPrizeRecord();
							dprd.setType(PrizeTypeEnum.R.getVal());
							dprd.setOpenId(openId);
							dprd.setPrizetime(new Date(nowtime));
							dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
							dprd.setCreatetime(new Date());
							if(!drawPrizeRecordService.insert(dprd)) {
								throw new ServiceException("生成中奖记录失败");
							}
							finallyPrizeIndex = PrizeTypeEnum.R.getVal();
						}
					}else {
						//错误
						throw new ServiceException("抽奖日期有误");
					}
				}
				
				//如果抽到参与奖
				else if(PrizeTypeEnum.N.getVal()==randN) {
					Prize pp = new Prize();
					pp.setType(PrizeTypeEnum.N.getVal());
					pp = this.find(pp);
					if(null==pp) {
						throw new ServiceException("奖品信息有误");
					}
					//本来是要重新抽奖的，但是因为抽到参与奖的概率很大，容易发生无限次递归调用导致StackOverflowError(堆栈异常)
					//所以抽到参与奖，无论数量是否为0，没有了就临时去买，都为参与奖。
					//int day14 = pp.getDay14();
					//if(0==day14) {
						//表示奖品已被抽走，重新抽奖
						//int randNN = this.getPrizeIndex(prizeList);
						//递归执行这个判断逻辑
						//finallyPrizeIndex = getFinallyPrizeIndex(prizeList, randNN, nowtime, day14s, day14e, day15s, day15e, day16s, day16e, day17s, day17e, day18s, day18e, openId);
					//}else {}
						//day14 = pp.getDay14()-1;
						//pp.setDay14(day14);
						//if(!this.updateById(pp)){
							//throw new ServiceException("更新奖品数量失败");
						//}
					
						//生成中奖记录
						DrawPrizeRecord dprd = new DrawPrizeRecord();
						dprd.setType(PrizeTypeEnum.N.getVal());
						dprd.setOpenId(openId);
						dprd.setPrizetime(new Date(nowtime));
						dprd.setIsExchange(PrizeTypeEnum.NO_EXCHANGE.getVal());
						dprd.setCreatetime(new Date());
						if(!drawPrizeRecordService.insert(dprd)) {
							throw new ServiceException("生成中奖记录失败");
						}
						finallyPrizeIndex = PrizeTypeEnum.N.getVal();
					
				}
				//都不满足上面的条件
				else {
					throw new ServiceException("奖品类型有误");
				}
				
				return  finallyPrizeIndex;
	}

	/**
	 * 因为jsp上面的值并不是0、1、2、3、4这样的值表示奖品
	 * 所以还需转换
	 */
	@Override
	public int getJspPrizeIndex(int index) {
		Random rand = new Random();
		int []  rArr = {5,9};
		int [] nArr = {2,4,6,8,10};
		if(PrizeTypeEnum.UTR.getVal()==index) {
			return 1;
		}else if(PrizeTypeEnum.SSR.getVal()==index) {
			return 3;
		}else if(PrizeTypeEnum.SR.getVal()==index) {
			return 7;
		}else if(PrizeTypeEnum.R.getVal()==index) {
			return rArr[rand.nextInt(rArr.length)];
		}else if(PrizeTypeEnum.N.getVal()==index) {
			return nArr[rand.nextInt(nArr.length)];
		}else {
			return nArr[rand.nextInt(nArr.length)];
		}
	}

}
